package com.zw.yzk.kabu.view.activity.imagedetails;

import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.View;
import android.view.animation.DecelerateInterpolator;
import android.widget.ImageView;

import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.bitmap.GlideBitmapDrawable;
import com.bumptech.glide.load.resource.drawable.GlideDrawable;
import com.bumptech.glide.request.animation.GlideAnimation;
import com.bumptech.glide.request.target.SimpleTarget;
import com.zw.yzk.kabu.utils.QNImageUtils;

import cn.finalteam.galleryfinal.widget.zoonview.PhotoViewAttacher;


public abstract class BaseImageDetailsActivity extends AppCompatActivity {

    private AnimatorSet currentAnimator;
    private Point globalOffset;

    protected abstract int getLayoutId();

    protected abstract String getEnterImageUrl();

    protected abstract Rect getStartRect();

    protected abstract ImageView getAnimatedImageView();

    protected abstract void onAnimatedEnd();


    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(getLayoutId());
        initData();
    }

    private void initData() {
        globalOffset = new Point();
        initImageView();
    }

    private void initImageView() {
        getWindow().getDecorView().post(new Runnable() {
            @Override
            public void run() {
                if (getStartRect() == null || TextUtils.isEmpty(getEnterImageUrl())) {
                    return;
                }
                playEnterAnimation(getAnimatedImageView());
            }
        });
    }

    /**
     * 进入页面动画
     */
    private void playEnterAnimation(final ImageView enterImage) {
        if (currentAnimator != null) {
            currentAnimator.cancel();
        }
        final Rect endRect = new Rect();
        enterImage.getGlobalVisibleRect(endRect, globalOffset);
        final Rect startRect = getStartRect();

        Glide.with(this).load(QNImageUtils.getThumbnail(this, getEnterImageUrl())).into(new SimpleTarget<GlideDrawable>() {
            @Override
            public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> glideAnimation) {
                if (resource instanceof GlideBitmapDrawable) {
                    enterImage.setImageBitmap(((GlideBitmapDrawable) resource).getBitmap());
                    PhotoViewAttacher attacher = new PhotoViewAttacher(enterImage);
                    attacher.setOnPhotoTapListener(new PhotoViewAttacher.OnPhotoTapListener() {
                        @Override
                        public void onPhotoTap(View view, float x, float y) {
                            finish();
                        }
                    });
                }
            }
        });

        startRect.offset(-globalOffset.x, -globalOffset.y);
        endRect.offset(-globalOffset.x, -globalOffset.y);
        float[] ratios = calculateRatios(startRect, endRect);

        enterImage.setPivotX(0.5f);
        enterImage.setPivotY(0.5f);
        final AnimatorSet enter = new AnimatorSet();
        enter.play(ObjectAnimator.ofFloat(enterImage, View.X, startRect.left, endRect.left))
                .with(ObjectAnimator.ofFloat(enterImage, View.Y, startRect.top, endRect.top))
                .with(ObjectAnimator.ofFloat(enterImage, View.SCALE_X, ratios[0], 1f))
                .with(ObjectAnimator.ofFloat(enterImage, View.SCALE_Y, ratios[1], 1f));

        enter.setDuration(400);
        enter.setInterpolator(new DecelerateInterpolator());
        enter.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
                currentAnimator = enter;
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                startRect.offset(globalOffset.x, globalOffset.y);
                currentAnimator = null;

                onAnimatedEnd();
            }

            @Override
            public void onAnimationCancel(Animator animation) {
                startRect.offset(globalOffset.x, globalOffset.y);
                currentAnimator = null;

                onAnimatedEnd();
            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
        enter.start();
    }

    /**
     * 退出页面动画
     */
    protected void playExitAnimation(ImageView existImage) {
        if (currentAnimator != null) {
            currentAnimator.cancel();
        }

        Rect endRect = getEndRect();
        Rect startRect = getStartRect();
        float[] ratios = calculateRatios(startRect, endRect);
        int deltaWidth = (int) (endRect.left * ratios[0]);
        int deltaHeight = (int) (endRect.top * ratios[1]);

        existImage.setPivotX(0.5f);
        existImage.setPivotY(0.5f);
        final AnimatorSet exit = new AnimatorSet();
        startRect.offset(-globalOffset.x, -globalOffset.y);
        endRect.offset(-globalOffset.x, -globalOffset.y);

        exit.play(ObjectAnimator.ofFloat(existImage, View.X, startRect.left - deltaWidth))
                .with(ObjectAnimator.ofFloat(existImage, View.Y, startRect.top - deltaHeight))
                .with(ObjectAnimator.ofFloat(existImage, View.SCALE_X, ratios[0]))
                .with(ObjectAnimator.ofFloat(existImage, View.SCALE_Y, ratios[1]));

        exit.setDuration(400);
        exit.setInterpolator(new DecelerateInterpolator());
        exit.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
                currentAnimator = exit;
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                currentAnimator = null;
                finish();
            }

            @Override
            public void onAnimationCancel(Animator animation) {
                currentAnimator = null;
            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
        exit.start();
    }

    /**
     * 获取endRect
     *
     * @return rect
     */
    private Rect getEndRect() {
        Rect endRect = new Rect();
        getAnimatedImageView().getGlobalVisibleRect(endRect, globalOffset);
        ImageView imageView = getAnimatedImageView();
        if (imageView != null && imageView.getDrawable() != null) {
            RectF rect = new RectF();
            Rect drawableRect = imageView.getDrawable().getBounds();
            Matrix imgMatrix = imageView.getImageMatrix();
            float[] matrixValues = new float[9];
            imgMatrix.getValues(matrixValues);
            rect.left = matrixValues[2];
            rect.top = matrixValues[5];
            rect.right = rect.left + drawableRect.width() * matrixValues[0];
            rect.bottom = rect.top + drawableRect.height() * matrixValues[4];

            if (rect.height() < endRect.height()) {
                endRect.top = (int) rect.top;
                endRect.bottom = (int) rect.bottom;
            }
        }
        return endRect;
    }

    /**
     * 计算缩放比
     *
     * @param startBounds 初始位置信息
     * @param finalBounds 结束位置信息
     * @return 宽高缩放比
     */
    private float[] calculateRatios(Rect startBounds, Rect finalBounds) {
        float[] result = new float[2];
        float widthRatio = (float) startBounds.width() / finalBounds.width();
        float heightRatio = (float) startBounds.height() / finalBounds.height();
        result[0] = widthRatio;
        result[1] = heightRatio;
        return result;
    }

    @Override
    public void finish() {
        super.finish();
        overridePendingTransition(0, android.R.anim.fade_out);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            playExitAnimation(getAnimatedImageView());
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }
}

